package com.weayer.service;

import com.weayer.constant.CommonStatusEnum;
import com.weayer.constant.IdentityConstants;
import com.weayer.constant.TokenConstants;
import com.weayer.dto.ResponseResult;
import com.weayer.remote.ServicePassengerUserClient;
import com.weayer.remote.ServiceVerificationcodeClient;
import com.weayer.request.SendVerificationCodeDTO;
import com.weayer.response.NumberCodeResponse;
import com.weayer.response.TokenResponse;
import com.weayer.util.JwtUtils;
import com.weayer.util.RedisPrefixUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @description:  Api服务 - 乘客 - 验证码service
 * @author: Weayer
 **/
@Service
public class VerificationCodeService {
    @Autowired
    private ServiceVerificationcodeClient serviceVerificationcodeClient;
    @Autowired
    private ServicePassengerUserClient servicePassengerUserClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * @Description: 生成验证码
     * @Param: [passengerPhone]
     * @return: com.weayer.dto.ResponseResult
     **/
    public ResponseResult generatorCode(String passengerPhone){
        // 调用验证码服务，获取6位验证码
        ResponseResult<NumberCodeResponse> numberCodeResponseResult = serviceVerificationcodeClient.getNumberCode(6);
        int numberCode = numberCodeResponseResult.getData().getNumberCode();
        // key, value 存入redis
        String key = RedisPrefixUtils.generatorKeyByPhone(passengerPhone, IdentityConstants.PASSENGER_IDENTITY);
        stringRedisTemplate.opsForValue().set(key, numberCode+"", 2, TimeUnit.MINUTES);
        // 通过短信服务商将验证码发送

//        JSONObject result = new JSONObject();
//        result.put("code", 1);
//        result.put("message", "success");
//        result.put("data", numberCode);

        return ResponseResult.success(numberCode);
    }

    /**
     * @Description: 验证码校验
     * @Param: [passengerPhone, verificationCode]
     * @return: com.weayer.dto.ResponseResult
     **/
    public ResponseResult checkCode(String passengerPhone, String verificationCode){
        // 根据手机号，redis中读取验证码
            // 1. 生成key 2. 获取value
        String key = RedisPrefixUtils.generatorKeyByPhone(passengerPhone, IdentityConstants.PASSENGER_IDENTITY);
        String codeRedis = stringRedisTemplate.opsForValue().get(key);

        // 验证码校验
        if(StringUtils.isBlank(codeRedis)){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_INVALID.getCode(), CommonStatusEnum.VERIFICATION_CODE_INVALID.getValue());
        }
        if(!codeRedis.trim().equals(verificationCode.trim())){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        // 判断原来是否有用户
        SendVerificationCodeDTO verificationCodeDTO = new SendVerificationCodeDTO();
        verificationCodeDTO.setPassengerPhone(passengerPhone);
        servicePassengerUserClient.loginOrRegister(verificationCodeDTO);

        // 生成2个 token 令牌
        String accessToken = JwtUtils.generatorToken(passengerPhone, IdentityConstants.PASSENGER_IDENTITY, TokenConstants.ACCESS_TOKEN_TYPE);
        String refreshToken = JwtUtils.generatorToken(passengerPhone, IdentityConstants.PASSENGER_IDENTITY, TokenConstants.REFRESH_TOKEN_TYPE);

        // 开启 redis 事务支持
        stringRedisTemplate.setEnableTransactionSupport(true);
        SessionCallback<Boolean> callback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                // 事务开始
                stringRedisTemplate.multi();
                try {
                    // 生成两个 tokenKey，然后存到redis 中
                    String accessTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, IdentityConstants.PASSENGER_IDENTITY, TokenConstants.ACCESS_TOKEN_TYPE);
                    String refreshTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, IdentityConstants.PASSENGER_IDENTITY, TokenConstants.REFRESH_TOKEN_TYPE);

//                    stringRedisTemplate.opsForValue().set(accessTokenKey, accessToken, 10, TimeUnit.SECONDS);     // 30 days
//                    stringRedisTemplate.opsForValue().set(refreshTokenKey, refreshToken, 60, TimeUnit.SECONDS);   // 31 days
                    operations.opsForValue().set(accessTokenKey, accessToken, 10, TimeUnit.SECONDS);
//                    int i = 1 / 0;
                    operations.opsForValue().set(refreshTokenKey, refreshToken, 60, TimeUnit.SECONDS);
                    // 事务提交
                    operations.exec();
                    return true;
                }catch (Exception e){
                    // 事务回滚
                    operations.discard();
                    return false;
                }
            }
        };
        Boolean execute = stringRedisTemplate.execute(callback);
        System.out.println("事务提交是否正常结束 " + execute);
        if(execute){
            // 响应
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setAccessToken(accessToken);
            tokenResponse.setRefreshToken(refreshToken);
            return ResponseResult.success(tokenResponse);
        }else{
            return ResponseResult.fail(CommonStatusEnum.CHECK_CODE_ERROR.getCode(), CommonStatusEnum.CHECK_CODE_ERROR.getValue());
        }
    }
}
